use std::{vec, time::SystemTime};

use snowflake::SnowflakeIdGenerator;

use crate::cli::conf::ConfCli;

/// 二进制传输协议
/// 
/// [起止符]    [终端ID]            [指令][数据包长度][数据包][奇偶校验位]              [起止符]<br>
/// [0x07 0x7E][64位[服务器ID默认0]][8位] [32位]     [n位]   [8位](取最后一位，其余保留)[0x07 0x7E]
/// 
/// 数据包长度 = 数据包.len
/// 
/// 奇偶校验位 = 数据包所有byte末位1的个数单双值
/// 
/// 起止符: 0x07 0x7E 
/// 
/// 数据冲突说明
/// 
/// 0x7E 改为 0x7D 0x01
/// 
/// 0x7D 改为 0x7D 0x02
#[derive(Debug)]
pub enum Cmd {
    // 心跳
    HEART,
    // 修改配置
    CONF,
    // 服务器发到终端
    Proxy2Cli,
    // 终端发到服务器
    Proxy2Server,
}

impl Cmd {
    fn get_cmd_by_index(index: u8) -> Self {
        match index {
            0x00 => {
                return Self::HEART
            },
            0x01 => {
                return Self::CONF
            },
            0x02 => {
                return Self::Proxy2Cli
            },
            0x03 => {
                return Self::Proxy2Server
            },
            _ => {
                return Self::HEART
            }
        }
    }

    fn get_index(&self) -> u8 {
        match &self {
            Self::HEART => {
                return 0x00;
            },
            Self::CONF => {
                return 0x01;
            },
            Self::Proxy2Cli => {
                return 0x02;
            },
            Self::Proxy2Server => {
                return 0x03;
            },
        }
    }
}

#[derive(Debug)]
pub struct Data {
    pub cmd: Cmd,
    pub data: Vec<u8>,
    pub cid: i64,
    // 随机任务ID
    pub pid: i64,
    pub create_time: SystemTime,
}

impl Data {
    fn new_cid(cmd: Cmd, data: Vec<u8>, cid: i64) -> Self {
        Self {
            cmd,
            data,
            cid,
            pid: SnowflakeIdGenerator::new(1, 2).generate(),
            create_time: SystemTime::now(),
        }
    }

    fn new_pid(cmd: Cmd, data: Vec<u8>, cid: i64, pid: i64) -> Self {
        Self {
            cmd,
            data,
            cid,
            pid,
            create_time: SystemTime::now(),
        }
    }

    fn new(cmd: Cmd, data: Vec<u8>) -> Self {
        Self::new_cid(cmd, data, ConfCli::get_conf().id)
    }

    // pub fn heart() -> Self {
    //     Self::new(Cmd::HEART, vec![])
    // }

    pub fn conf() -> Self {
        let a = serde_json::to_string(&ConfCli::get_conf()).unwrap();
        let b = a.as_bytes();
        Self::new(Cmd::CONF, b.to_vec())
    }

    pub fn proxy_cli(data: Vec<u8>, cid: i64, pid: i64) -> Self {
        Self::new_pid(Cmd::Proxy2Cli, data, cid, pid)
    }

    pub fn proxy_server(data: Vec<u8>, cid: i64, pid: i64) -> Self {
        Self::new_pid(Cmd::Proxy2Server, data, cid, pid)
    }

    fn get_validate(&self) -> u8 {
        let mut data = vec![];
        data.append(&mut ilong_to_bytes(self.cid));
        data.append(&mut ilong_to_bytes(self.pid));
        data.push(self.cmd.get_index());
        data.append(&mut uint_to_bytes(self.data.len()));
        data.append(&mut self.data.clone());
        compute_validate(&data)
    }

    pub fn to_vec(&self) -> Vec<u8> {
        let mut result: Vec<u8> = vec![];
        result.append(&mut DATA_START.to_vec());

        let mut body: Vec<u8> = vec![];
        body.append(&mut ilong_to_bytes(self.cid).to_vec());
        body.append(&mut ilong_to_bytes(self.pid).to_vec());
        body.push(self.cmd.get_index());
        body.append(&mut uint_to_bytes(self.data.len()));
        body.append(&mut self.data.clone());
        body.push(self.get_validate().clone());
        result.append(&mut escape(body));

        result.append(&mut DATA_START.to_vec());
        result
    }
}

fn uint_to_bytes(int: usize) -> Vec<u8> {
    let mut byte_vec = vec![];
    for i in (0..4).rev() {
        byte_vec.push((int >> (i * 8)) as u8);
    }
    byte_vec
}

fn bytes_to_uint(bytes: Vec<u8>) -> usize {
    let mut uint = 0;
    for i in 0..4 {
        uint = uint + ((bytes[i] as usize) << ((3 - i) * 8));
    }
    uint
}

fn ilong_to_bytes(long: i64) -> Vec<u8> {
    let ulong = long as u64;
    let mut byte_vec = vec![];
    for i in (0..8).rev() {
        byte_vec.push((ulong >> (i * 8)) as u8);
    }
    byte_vec
}

pub fn bytes_to_ilong(bytes: Vec<u8>) -> i64 {
    let mut ulong = 0;
    for i in 0..8 {
        ulong = ulong + ((bytes[i] as u64) << ((7 - i) * 8));
    }
    ulong as i64
}

// 起止符
static DATA_START: [u8; 2] = [0x07, 0x7E];

// 转换符
static ESCAPE_7E: [u8; 2] = [0x7D, 0x01];
static ESCAPE_7D: [u8; 2] = [0x7D, 0x02];

// 从原数组获取data
pub fn get_datas(data: Vec<u8>) -> (Vec<Data>, Vec<u8>) {
    let mut result: Vec<Data> = vec![];
    let mut len;
    let mut temp_data = data;
    loop {
        let (sub_data, result_data) = sub_if_end(temp_data.clone());
        temp_data = result_data;
        if sub_data.is_some() {
            result.push(sub_data.unwrap());
            len = temp_data.len();
            if len == 0 {
                break;
            }
        } else {
            break;
        }
    }
    return (result, temp_data)
}

// 如果有一条完整数据 就取出 并返回剩余数组
// 如果数据异常 返回第二个FLAG（包含第二个FLAG）以后的数组
// 如果数据正常且没有完整数据 返回原数组
fn sub_if_end(data: Vec<u8>) -> (Option<Data>, Vec<u8>) {
    let mut hit_times = 0;
    let mut index: usize = 0;
    for i in 0..data.len() - 1 {
        if hit_times == 2 {
            break;
        }
        if data[i..i + 2] == DATA_START {
            hit_times = hit_times + 1;
            index = i + 2;
        }
    }
    if hit_times == 2 {
        let valid_data = data[0..index].to_vec();
        match to_data(valid_data) {
            Ok(d) => {
                return (Option::Some(d), data[index..].to_vec());
            },
            Err(_) => {
                return (Option::None, data[(index - 2)..].to_vec())
            }
        }
    } else {
        return (Option::None, data);
    }
}

// 去除前后FLAG
fn remove_flag(data: Vec<u8>) -> Vec<u8> {
    data[2..(data.len() - 2)].to_vec()
}

// byte反转义
// 将0x7D 0x01 转为 0x7E
// 将0x7D 0x02 转为 0x7D
fn deescape(mut data: Vec<u8>) -> Vec<u8> {
    let mut index = 0;
    for _ in 0..data.len() {
        if index + 1 >= data.len() {
            break;
        }
        if data[index..index + 2] == ESCAPE_7E {
            data[index] = DATA_START[1];
            data.remove(index + 1);
        } else if data[index..index + 2] == ESCAPE_7D {
            data[index] = ESCAPE_7D[0];
            data.remove(index + 1);
        }
        index = index + 1;
    }
    data
}

/// byte转义
/// 
/// 将0x7E 转为 0x7D 0x01
/// 
/// 将0x7D 转为 0x7D 0x02
fn escape(mut data: Vec<u8>) -> Vec<u8> {
    let mut index = 0;
    for _ in 0..data.len() {
        if data[index] == DATA_START[1] {
            data[index] = ESCAPE_7E[0];
            data.insert(index + 1, ESCAPE_7E[1]);
            index = index + 1;
        } else if data[index] == ESCAPE_7D[0] {
            data.insert(index + 1, ESCAPE_7D[1]);
            index = index + 1;
        }
        index = index + 1;
    }
    data
}

/// 转换为data实体
/// 如果失败
/// 返回清除第一个FLAG之后的byte
fn to_data(data: Vec<u8>) -> Result<Data, std::fmt::Error> {
    let after_remove_flag_data = remove_flag(data);
    let after_escape_data = deescape(after_remove_flag_data);
    let mut index = 0;
    let cid = bytes_to_ilong(after_escape_data[index..index + 8].to_vec());
    index = index + 8;
    let pid = bytes_to_ilong(after_escape_data[index..index + 8].to_vec());
    index = index + 8;
    let cmd = after_escape_data[index];
    index = index + 1;
    let len = bytes_to_uint(after_escape_data[index..index + 4].to_vec());
    index = index + 4;
    let cli_data = after_escape_data[index..(index + len)].to_vec();
    let compute_validate = compute_validate(&after_escape_data[0..(index + len)].to_vec());
    let result_validate = after_escape_data[(index + len)] & 0x01;
    if compute_validate != result_validate {
        return Result::Err(std::fmt::Error)
    }
    return Result::Ok(Data::new_pid(Cmd::get_cmd_by_index(cmd), cli_data, cid, pid))
}

// 计算校验值
fn compute_validate(data: & Vec<u8>) -> u8 {
    let mut num: usize = 0;
    for b in data {
        if (*b & 0x01) == 0x01 {
            num = num + 1;
        } 
    }
    (num % 2) as u8
}